package com.medical.admin.text;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class SignGenerator {

    private static final String COOPERATION_SECRET = "test_ty168ty168"; // 替换为实际密钥

    /**
     * 生成签名
     *
     * @param body 请求体中的body节点
     * @return MD5签名（大写）
     */
    public static String generateSign(Map<String, Object> body) throws Exception {
        // 1. 处理body参数，生成待签名字符串
        String paramsString = processParams(body);

        // 2. 拼接密钥（头尾各加一次）
        String rawSignString = COOPERATION_SECRET + paramsString + COOPERATION_SECRET;

        // 3. 计算MD5并转为大写
        return calculateMD5(rawSignString);
    }

    /**
     * 处理参数，生成待签名字符串
     *
     * @param params 参数（Map或List）
     * @return 拼接后的字符串
     */
    private static String processParams(Object params) {
        if (params instanceof Map) {
            // 处理Map类型，按键名严格排序
            TreeMap<String, Object> sortedMap = new TreeMap<>((Map<String, Object>) params);
            StringBuilder sb = new StringBuilder();
            sortedMap.forEach((key, value) -> {
                if (value != null) { // 跳过null值，保留空字符串
                    sb.append(key).append(processValue(value));
                }
            });
            return sb.toString();
        } else if (params instanceof List) {
            // 处理数组类型，保持元素顺序
            StringBuilder sb = new StringBuilder();
            for (Object item : (List<?>) params) {
                sb.append(processValue(item));
            }
            return sb.toString();
        } else if (params == null) {
            return ""; // null值直接返回空字符串
        } else {
            // 基本类型直接转为字符串（空字符串保留）
            return params.toString();
        }
    }

    /**
     * 处理值（递归处理嵌套结构）
     *
     * @param value 参数值
     * @return 拼接后的字符串
     */
    private static String processValue(Object value) {
        if (value instanceof Map || value instanceof List) {
            // 递归处理嵌套结构
            return processParams(value);
        } else if (value == null) {
            return ""; // 忽略null值
        } else {
            return value.toString();
        }
    }

    /**
     * 计算MD5（确保每个字节转为两位十六进制）
     *
     * @param input 输入字符串
     * @return MD5签名（大写）
     */
    private static String calculateMD5(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));

        StringBuilder hexString = new StringBuilder();
        for (byte b : digest) {
            hexString.append(String.format("%02X", b)); // 强制两位大写
        }
        return hexString.toString();
    }

    // 测试用例
    public static void main(String[] args) throws Exception {
        //---------------- 测试空body场景 -----------------
        Map<String, Object> emptyBody = new TreeMap<>();
        String emptySign = generateSign(emptyBody);
        System.out.println("空body签名: " + emptySign);
        // 预期输出：test_ty168ty168test_ty168ty168 的MD5
        // 示例：723761********1c40b129d2aa95f04b

        //---------------- 测试带数组的body -----------------
//        Map<String, Object> ticket1 = new TreeMap<>();
//        ticket1.put("passengerName", "测试六");
//        ticket1.put("certificate", 1);
//        ticket1.put("certificateNo", "310109198501122017");
//        ticket1.put("price", 199.00);
//
//        Map<String, Object> ticket2 = new TreeMap<>();
//        ticket2.put("passengerName", "测试五");
//        ticket2.put("certificate", 1);
//        ticket2.put("certificateNo", "310109198501122015");
//        ticket2.put("price", 199.00);
//
//        List<Map<String, Object>> tickets = new ArrayList<>();
//        tickets.add(ticket1);
//        tickets.add(ticket2);

        Map<String, Object> body = new TreeMap<>();
//        body.put("tickets", tickets);

        String sign = generateSign(body);
        System.out.println("带数组的签名: " + sign);
    }
}
